# !/usr/bin/env python
#
# Copyright 2010 Rob Stenzinger 
#
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

__author__ = 'Rob Stenzinger'

import logging
import email
import datetime
from google.appengine.ext import webapp 
from google.appengine.ext.webapp.mail_handlers import InboundMailHandler 
from google.appengine.ext.webapp.util import run_wsgi_app
from google.appengine.ext import db
from google.appengine.api import memcache
from google.appengine.api import users
from google.appengine.api import mail

import parsedatetime.parsedatetime as pdt 
import parsedatetime.parsedatetime_consts as pdc 

import time

import model
import blog
from model import Archive,Weblog,WeblogReactions,Book,Images,Tag,Feeds,Flash,Audio,Video
import authorized
import view
import util

template_image = """<img src='__file__' alt='' title=''>"""
template_flash = """
<script type="text/javascript">
var flashvars = {};
var params = {};
var attributes = {};
swfobject.embedSWF("__file__", "myAlternativeContent___file__", "700", "525", "9.0.0", "/js/swfobject/expressInstall.swf", flashvars, params, attributes);
</script>
<div id="myAlternativeContent___file__">
<a href="http://www.adobe.com/go/getflashplayer">
<img src="http://www.adobe.com/images/shared/download_buttons/get_flash_player.gif" alt="Get Adobe Flash player" />
</a>
</div>
"""
template_audio = """
"""
template_video = """
"""

class MailHandler(InboundMailHandler):
    config = None
    
    def receive(self, message):
        util.getLogger(__name__).debug("Received a message from: " + message.sender)
        #util.getLogger(__name__).debug("Theme asset name: %s" % filename)  
        decoded_plain_list = list()
        
        if self.config is None:
            self.config = util.get_config()
        
        try:
            plaintext_bodies = message.bodies('text/plain')
            for content_type, body in plaintext_bodies:
                #util.getLogger(__name__).debug("NOT decoded plain text: ")
                #util.getLogger(__name__).debug(body)                
                decoded_plain_list.append(body.decode())
                #logging.info(body)        
        except Exception,e:
            util.getLogger(__name__).debug("plain text error:")
            util.getLogger(__name__).debug(e)                
            
#        try:
#            html_bodies = message.bodies('text/html')
#            for content_type, body in html_bodies:
#                decoded_html = body.decode()
#                util.getLogger(__name__).debug("decoded html: ")
#                logging.info(decoded_html)
#        except Exception,e:
#            util.getLogger(__name__).debug("html error:")
#            util.getLogger(__name__).debug(e)                
            
        try:
            attachments = []
            attachments_list = []
            if message.attachments:
                if isinstance(message.attachments[0], basestring):
                    attachments = [message.attachments]
                else:
                    attachments = message.attachments
            
            if len(attachments) > 0:
                for filename, content in attachments:
                    util.getLogger(__name__).debug("found attached file: " + filename)
                    attachments_list.append({'filename':filename,
                                             'file':content.decode()
                                             })
        except Exception,e:
            util.getLogger(__name__).debug("attachment error:")
            util.getLogger(__name__).debug(e)


        # add attachments to the database if they're allowed:
        allowed_attachments = ["png","jpg","mp3","mp4","swf"]
        uploaded_attachments = []
        for attachment in attachments_list:
            for extension in allowed_attachments:
                if attachment["filename"].lower().endswith(extension): 
                    if extension in ["png","jpg"]:
                        attachment["key"] = insert_image(attachment["file"],attachment["filename"])
                        attachment["type"] = "image"
                        uploaded_attachments.append(attachment)
                    elif extension == "mp3":
                        attachment["key"] = insert_audio(attachment["file"],attachment["filename"])
                        attachment["type"] = "audio"
                        uploaded_attachments.append(attachment)
                    elif extension == "swf":
                        attachment["key"] = insert_flash(attachment["file"],attachment["filename"])
                        attachment["type"] = "flash"
                        uploaded_attachments.append(attachment)
                    elif extension == "mp4":
                        attachment["key"] = insert_video(attachment["file"],attachment["filename"])
                        attachment["type"] = "video"
                        uploaded_attachments.append(attachment)
                    
            
            
        content = ""
        status = None
        entrytype = None
        tags = None
        chapter = None
        book = None
        date = None
        
        #parse content from message... 
        
        plain_email = "\n".join(decoded_plain_list)
        settings_start = plain_email.find("---")
        email_settings_section = plain_email[0:settings_start]        
        email_settings_raw_list = email_settings_section.split("\n")
        util.getLogger(__name__).debug(email_settings_raw_list) 
        
        if settings_start == -1:
            settings_start = 0
            
        content = plain_email[settings_start+3:len(plain_email)].strip()
        content_result = []

        #determine the post settings, e.g. type of post, is it a comic, a page, a blog entry, etc.
        for item in email_settings_raw_list:     
            if len(item) > 0:  
                util.getLogger(__name__).debug(item)
                split_position = item.find(":")
                label = item[0:split_position].strip()
                value = item[split_position+1:len(item)].strip()
                util.getLogger(__name__).debug(label + "---" + value)
                if label.lower() == "status":
                    status = value
                elif label.lower() == "book":
                    book = value
                elif label.lower() == "chapter":
                    chapter = value
                elif label.lower() == "date":
                    date = value
                elif label.lower() == "tags":
                    tags = value
                elif label.lower() == "type":
                    entrytype = value
                            
        #replace content placeholders in email:
        for attachment in uploaded_attachments:
            if content.find(attachment["filename"]) > -1:
                placeholder = "__" + attachment["filename"] + "__"
                content_lines = content.split("\n")
                comic_added = False
                for line in content_lines:
                    if content.find(placeholder) > -1:
                        if entrytype == "comic" and comic_added == False:
                            line = line.replace(placeholder, "[comic]" + get_template(attachment["type"], attachment["key"]) + "[/comic]")
                            comic_added = True
                        else:                                              
                            line = line.replace(placeholder, get_template(attachment["type"], attachment["key"]))
                    content_result.append(line)
                content = "\n".join(content_result)

        if status is None:
            status = "draft"
            
        if date is None:
            date = "Today"
            
        date = parseDate(date)
        
        if entrytype not in model.config_post_types:
            entrytype =  model.config_post_default
            
        user = users.get_current_user()
        post = Weblog()
        post.title = message.subject 
        post.content = content 
        post.status = status                        
        
        post.chapter = chapter
        post.book = book 
        post.author = user
        try:
            post.authorEmail = user.email()
        except Exception,e:
            #todo: 
            pass
        
        post.date = date
        post.tags_commas = tags
            
        post.entrytype = entrytype
        post.permalink = blog.get_permalink(post.title)
        
        post.save()
        util.flushBlogMonthCache(post)
        util.flushBlogPagesCache()
        util.flushTagList()
        
        post_url = self.config["root_url"] + post.permalink
        admin_email_body = self.config["mail_new_post_body"]
        admin_email_body = admin_email_body.replace("__post_url__", post_url)
        admin_email_body = admin_email_body.replace("__post_title__", post.title)
        mail.send_mail_to_admins(self.config["mail_new_post_from_email"], self.config["mail_new_post_subject"], admin_email_body)


def parseDate(s):
    # create an instance of Constants class so we can override some of the defaults
    c = pdc.Constants()
    # create an instance of the Calendar class and pass in our Constants # object instead of letting it create a default
    p = pdt.Calendar(c)
    
    util.getLogger(__name__).debug("parsing date...") 
    util.getLogger(__name__).debug(p)
    
    result = p.parse(s) 
    util.getLogger(__name__).debug(result)
    return datetime.datetime(time.struct_time(result[0]).tm_year,time.struct_time(result[0]).tm_mon,time.struct_time(result[0]).tm_mday,time.struct_time(result[0]).tm_hour,time.struct_time(result[0]).tm_min,time.struct_time(result[0]).tm_sec)

def insert_image(image_data, image_filename): #, image_url=None):
    fileexists = Images.all().filter('filename =',image_filename).fetch(1)
    if fileexists == []:    
        images = Images()
        images.filename = image_filename
            
        images.image = db.Blob(image_data)
        key = images.put()
        return "%s" % (key)
    else:
        return "%s" % (fileexists[0].key())

def insert_flash(file_data, file_name):
    fileexists = Flash.all().filter('filename =',image_filename).fetch(1)
    if fileexists == []:
        store_file = model.Flash()        
        store_file.filename = file_name
        store_file.swf = db.Blob(file_data)
        store_file.uploader = users.GetCurrentUser()
        key = store_file.put()
        return "%s" % (key)
    else:
        return "%s" % (fileexists[0].key())

def insert_audio(file_data, file_name):
    fileexists = Audio.all().filter('filename =',image_filename).fetch(1)
    if fileexists == []:
        store_file = model.Audio()        
        store_file.filename = file_name
        store_file.mp3 = db.Blob(file_data)
        store_file.uploader = users.GetCurrentUser()
        key = store_file.put()         
        return "%s" % (key)
    else:
        return "%s" % (fileexists[0].key())
    
def insert_video(file_data, file_name):
    fileexists = Video.all().filter('filename =',image_filename).fetch(1)
    if fileexists == []:
        store_file = model.Video()        
        store_file.filename = file_name
        store_file.mp4 = db.Blob(file_data)
        store_file.uploader = users.GetCurrentUser()
        key = store_file.put()         
        return "%s" % (key)
    else:
        return "%s" % (fileexists[0].key())
    
def get_template(type, filedatastorekey):
    file_url = ""
    
    if type == "image":
        file_url = "/rpc/image/" + filedatastorekey
        return template_image.replace("__file__", file_url)
    elif type == "flash":        
        file_url = "/rpc/flash/" + filedatastorekey
        return template_flash.replace("__file__", file_url)
    elif type == "audio":        
        file_url = "/rpc/audio/" + filedatastorekey
        return template_audio.replace("__file__", file_url)
    elif type == "video":        
        file_url = "/rpc/video/" + filedatastorekey
        return template_video.replace("__file__", file_url)




def main():
    application = webapp.WSGIApplication([
        MailHandler.mapping()
        ], debug=True)
    run_wsgi_app(application)

if __name__ == "__main__":
    main()